import jmcvideo.*;

String movName = "movie.wmv";
JMCMovie mov;

boolean initialized = false;
 PVector spot;
 
void setup(){
  size(800, 600,P2D);
  background(0);
  frame.setResizable(true);
  mov = new JMCMovie(this, movName);
  mov.loop();
stroke(color(0,255,0));
      noFill();

  //spot = new PVector(20,20);
}


// Called every time a new frame is available to read
void videoFrameUpdated(JMCMovie m) {
  m.read();
  initialized = true;
}

float millisold = 0;

void draw(){  
      
      image(mov, 0, 0);    
      Blob[] b = findBlobs(mov);
      
      for(int i = 0; i < b.length; i++){
        rect(b[i].minX, b[i].minY, b[i].maxX - b[i].minX, b[i].maxY - b[i].minY);        
      }
      
}


Blob[] findBlobs(PImage img){
  MutableIntRef[][] mx = new MutableIntRef[img.width][img.height];
  for(int x = 0; x < img.width; x++){
    for(int y = 0; y < img.height; y++){
      mx[x][y] = new MutableIntRef();
    }
  }

  Map blobMap = new HashMap();

  float gray;  
  color px;
  Integer currentBlobId;
  int lastIdValue = 0;
  Blob currBlob;
  Blob blobAux;
  float tolerance = 200;

  for(int y = 0; y < img.height; y++){
    for(int x = 0; x < img.width; x++){
      px = img.get(x, y);
      gray = red(px) + green(px) + blue(px);

      if(gray > tolerance){
        if(x>0 && mx[x-1][y].getVal() != -1){
          // copy
          mx[x][y].setRef(mx[x-1][y].getRef());
        } // if something to the left
        
        if(y>0 && mx[x][y-1].getVal() != -1){
          if(mx[x][y].getVal() == -1){
            // copy
            mx[x][y].setRef(mx[x][y-1].getRef());
          } // if nothing here
          else{
            if(mx[x][y].getRef() != mx[x][y-1].getRef()){
                // Make the blob to the left part of the current blob
                // Update the data on the current blob as needed
                currBlob = (Blob)blobMap.get(mx[x][y].getVal()); 
                blobAux  = (Blob)blobMap.get(mx[x][y-1].getVal());
  
                currBlob.minX = min(blobAux.minX, currBlob.minX);
                currBlob.minY = min(blobAux.minY, currBlob.minY);
                currBlob.maxX = max(blobAux.maxX, currBlob.maxX);
                currBlob.maxY = max(blobAux.maxY, currBlob.maxY);
                currBlob.pxCount += blobAux.pxCount;
  
                // The blob above is absorbed by the current blob
                blobMap.remove(new Integer(blobAux.id));
                mx[x][y-1].setRef(mx[x][y].getRef());
            } // if not the same thing
              
            
            
          } // if something here
          
        } // if something above
          // New blob isolated from the others
            if(mx[x][y].getVal() == -1){
              // Nothing up or to the left: new blob
              currBlob = new Blob();
              currBlob.id = lastIdValue++;
              currBlob.minX = x;
              currBlob.maxX = x;
              currBlob.minY = y;
              currBlob.maxY = y;
              currBlob.pxCount = 1;
              blobMap.put(new Integer(currBlob.id), currBlob);
              mx[x][y].setVal(currBlob.id);
            } 
            else {
              // Part of another blob: update it
              currBlob = (Blob)blobMap.get(new Integer(mx[x][y].getVal()));
              
              currBlob.minX = min(x, currBlob.minX);
              currBlob.minY = min(y, currBlob.minY);
              currBlob.maxX = max(x, currBlob.maxX);
              currBlob.maxY = max(y, currBlob.maxY);
              currBlob.pxCount++;
            }// if this position has a new blob
      } // if gray > tolerance
    } // y
  } // x
/*
 for(Iterator it = blobMap.values().iterator(); it.hasNext();){
    Blob b = (Blob)it.next();
    println(b.id);
  }*/
  /*
  for(int y = 0; y < img.height; y++){
    for(int x = 0; x < img.width; x++){
      println(x + " " + y +" " +mx[x][y].getVal());
    }
    println();
  }*/
  return (Blob[]) blobMap.values().toArray(new Blob[blobMap.values().size()]); 
} // findBlobs


